#pragma once

#include "types.h"

template <typename T>
struct base_memory_block {
public:
	using value_t = T;

private:
	T* const _data;

public:
	constexpr base_memory_block(T* data): _data{ data } {}

	constexpr size_t size() const {
		const size_t offset = sizeof(size_t) / sizeof(T);
		const auto mem_size = *reinterpret_cast<size_t*>(_data - offset);
		return mem_size;
	}

	constexpr T* operator&() const { return _data; }

	constexpr T* operator+(size_t offset) const {
		if (offset >= size()) [[unlikely]] {
			throw std::bad_alloc;
		}

		return _data + offset;
	}

	constexpr T& operator*() { return *_data; }

	constexpr T& operator[](size_t pos) { return _data[pos]; }
};

using memory_block = base_memory_block<byte>;